﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YiTian.Core.Modularity
{
    public class ModuleLoader : IModuleLoader
    {
        private readonly IModuleDiscoverer _moduleDiscoverer; // 模块发现器（查找DLL中的模块）

        public ModuleLoader(IModuleDiscoverer moduleDiscoverer)
        {
            _moduleDiscoverer = moduleDiscoverer;
        }

        public List<IModule?> LoadModules(string moduleDirectory, string dllNamePattern = "*.Module.dll")
        {
            // 1. 发现符合规则的模块DLL（如名称匹配 *.Module.dll）
            var moduleAssemblies = _moduleDiscoverer.Discover(moduleDirectory, dllNamePattern);


            // 2. 提取模块类型（排除抽象类）
            var moduleTypes = moduleAssemblies
                .SelectMany(asm => asm.GetTypes())
                .Where(type => typeof(IModule).IsAssignableFrom(type) && !type.IsAbstract && !type.IsInterface)
                .ToList();

            // 3. 解析模块依赖关系，生成加载顺序（确保依赖先加载）
            var sortedModules = SortModulesByDependency(moduleTypes);

            // 4. 实例化模块（不执行初始化，仅为服务配置做准备）
            return sortedModules.Select(type => (IModule)Activator.CreateInstance(type)).ToList();
        }

        // 解析依赖并排序（拓扑排序）
        private List<Type> SortModulesByDependency(List<Type> moduleTypes)
        {
            var dependencyGraph = new Dictionary<Type, List<Type>>();
            foreach (var type in moduleTypes)
            {
                var module = (ModuleBase)Activator.CreateInstance(type); // 临时实例化获取依赖
                var dependencies = module.GetDependencies()
                    .Where(depType => moduleTypes.Contains(depType)) // 仅保留已发现的模块依赖
                    .ToList();
                dependencyGraph[type] = dependencies;
            }

            // 拓扑排序（处理依赖顺序）
            return TopologicalSort(dependencyGraph);
        }

        // 初始化模块（按排序后的顺序执行Initialize）
        private List<IModule> InitializeModules(List<Type> sortedModuleTypes)
        {
            var modules = new List<IModule>();
            foreach (var type in sortedModuleTypes)
            {
                var module = (IModule)Activator.CreateInstance(type);
                var context = new ModuleInitializationContext(modules.AsReadOnly(), null); // 可传入实际ServiceProvider
                module.Initialize(context);
                modules.Add(module);
            }
            return modules;
        }

        // 拓扑排序算法（处理依赖顺序）
        private List<Type> TopologicalSort(Dictionary<Type, List<Type>> graph)
        {
            var visited = new HashSet<Type>();
            var tempVisited = new HashSet<Type>(); // 临时标记，用于检测循环
            var result = new List<Type>();

            foreach (var node in graph.Keys)
            {
                if (!visited.Contains(node))
                {
                    if (HasCycle(node, graph, visited, tempVisited))
                    {
                        throw new InvalidOperationException($"检测到模块循环依赖：{node.FullName}");
                    }
                    Dfs(node, graph, visited, result);
                }
            }

            result.Reverse();
            return result;
        }

        // 检测是否存在循环依赖
        private bool HasCycle(Type node, Dictionary<Type, List<Type>> graph, HashSet<Type> visited, HashSet<Type> tempVisited)
        {
            if (tempVisited.Contains(node))
                return true; // 检测到循环

            if (visited.Contains(node))
                return false;

            tempVisited.Add(node);
            foreach (var dependency in graph[node])
            {
                if (HasCycle(dependency, graph, visited, tempVisited))
                    return true;
            }
            tempVisited.Remove(node);
            visited.Add(node);
            return false;
        }

        private void Dfs(Type node, Dictionary<Type, List<Type>> graph, HashSet<Type> visited, List<Type> result)
        {
            visited.Add(node);
            foreach (var dependency in graph[node])
            {
                if (!visited.Contains(dependency))
                {
                    Dfs(dependency, graph, visited, result);
                }
            }
            result.Add(node);
        }
    }
}
